package ldh.im.fxbase.dao;

import ldh.im.fxbase.data.pojo.ImGroup;
import ldh.im.fxbase.data.pojo.ImGroupUser;
import ldh.im.fxbase.data.pojo.ImUser;
import ldh.im.fxbase.data.pojo.ext.ImGroupUserExt;
import ldh.im.fxbase.util.DbUtil;
import ldh.im.fxbase.util.ImCacheFactory;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class ImGroupUserDao extends BaseDao {

    private static final String TABLE_NAME = "im_group_users";
    private static final String GU_COLUMNS = "gu.id, gu.userId, gu.userName, gu.groupId, gu.remark, gu.isShowName showName, gu.isWaking, " +
            "gu.isTop top, gu.isDisturb disturb, gu.ext1, gu.ext2, gu.status statusValue, gu.createTime, gu.updateTime";

    public void batchInserts(ImGroup imGroup) throws SQLException {
        if (imGroup.getGroupUserSet() == null || imGroup.getGroupUserSet().size() < 1) return;
        DbUtil.transaction((queryRunner, connection) -> {
            Set<ImGroupUser> imUserSet = imGroup.getGroupUserSet();
            Object[][] paras =
                    imUserSet.stream().map(u-> new Object[] {u.getUserId(), u.getUserName(), imGroup.getId(), u.getRemark(), u.getShowName(), u.getWaking(),
                            u.getTop(), u.getDisturb(), u.getExt1(),
                            u.getExt2(), valueEnum(u.getStatus()), imGroup.getCreateTime(), imGroup.getUpdateTime()}).toArray(Object[][]::new);
            String sql = String.format("insert into im_group_user(userId, userName, groupId, remark, isShowName, isWaking, isTop, isDisturb, " +
                    "ext1, ext2, status, createTime, updateTime) " +
                    "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
            int[] ids = queryRunner.batch(connection, sql, paras);
            return ids;
        });
    }

    public void batchUpdates(List<ImGroupUser> groupUsers) throws SQLException {
        if (groupUsers.size() < 1) return;
        DbUtil.transaction((queryRunner, connection) -> {
            Object[][] paras = groupUsers.stream().map(gu-> new Object[] {gu.getUserName(), gu.getRemark(), gu.getShowName(), gu.getWaking(),
                    gu.getTop(), gu.getDisturb(), gu.getExt1(), gu.getExt2(),
                    gu.getUpdateTime(), gu.getGroupId(), gu.getUserId()}).toArray(Object[][]::new);
            String sql = String.format("update im_group_user set userName = ?, remark = ?, isShowName = ?, isWaking = ?, isTop = ?, isDisturb = ?, " +
                    "ext1 = ?, ext2 = ?, updateTime = ? where groupId = ? and userId = ?");
            int[] ns = queryRunner.batch(connection, sql, paras);
            if (ns.length != groupUsers.size()) {
               throw new RuntimeException("批量更新失败!");
            }
            return ns;
        });
    }

    public void addGroupUsers(ImGroup imGroup, Set<ImUser> imUserSet) throws SQLException {
        DbUtil.transaction((queryRunner, connection) -> {
            Object[][] paras = imUserSet.stream().map(u-> new Object[] {u.getUserId(), u.getUserName(), imGroup.getId(), null, true, false, false, true, null, null,
                            imGroup.getCreateTime(), imGroup.getUpdateTime()}).toArray(Object[][]::new);
            String sql = String.format("insert into im_group_user(userId, userName, groupId, remark, isShowName, isWaking, isTop, isDisturb, " +
                    "ext1, ext2, createTime, updateTime) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
            int[] ids = queryRunner.batch(connection, sql, paras);
            return ids;
        });
    }

    public void update(ImGroupUser groupUser) throws SQLException {
        DbUtil.transaction((queryRunner, connection) -> {
            String sql = String.format("update im_group_user set userName = ?, remark = ?, isShowName = ?, isWaking = ?, isTop = ?, isDisturb = ?, " +
                    "ext1 = ?, ext2 = ?, updateTime = ? where groupId = ? and userId = ?");
            int n = queryRunner.update(connection, sql, groupUser.getUserName(), groupUser.getRemark(), groupUser.getShowName(), groupUser.getWaking(),
                    groupUser.getTop(), groupUser.getDisturb(), groupUser.getExt1(), groupUser.getExt2(),
                    groupUser.getUpdateTime(), groupUser.getGroupId(), groupUser.getUserId());
            return n;
        });
    }

    public void insertOrUpdates(List<ImGroupUser> groupUsers) throws SQLException {
        if (groupUsers.size() < 1) return;
        DbUtil.transaction((queryRunner, connection) -> {
            Object[][] paras = groupUsers.stream().map(gu-> new Object[] {gu.getUserName(), gu.getRemark(), gu.getShowName(), gu.getWaking(),
                    gu.getTop(), gu.getDisturb(), gu.getExt1(), gu.getExt2(),
                    gu.getUpdateTime(), gu.getGroupId(), gu.getUserId()}).toArray(Object[][]::new);
            String sql = String.format("update im_group_user set userName = ?, remark = ?, isShowName = ?, isWaking = ?, isTop = ?, isDisturb = ?, " +
                    "ext1 = ?, ext2 = ?, updateTime = ? where groupId = ? and userId = ?");
            int[] ns = queryRunner.batch(connection, sql, paras);
            List<ImGroupUser> insertGroupUsers = new ArrayList<>();
            int idx = 0;
            for (int n : ns) {
                if (n != 1) {
                    insertGroupUsers.add(groupUsers.get(idx));
                }
                idx++;
            }

            Object[][] paras2 =
                    insertGroupUsers.stream().map(u-> new Object[] {u.getUserId(), u.getUserName(), u.getGroupId(), u.getRemark(), u.getShowName(), u.getWaking(),
                            u.getTop(), u.getDisturb(), u.getExt1(),
                            u.getExt2(), valueEnum(u.getStatus()), new Date(), u.getUpdateTime()}).toArray(Object[][]::new);
            String sql2 = String.format("insert into im_group_user(userId, userName, groupId, remark, isShowName, isWaking, isTop, isDisturb, " +
                    "ext1, ext2, status, createTime, updateTime) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
            int[] ns2 = queryRunner.batch(connection, sql2, paras2);

            return ns;
        });
    }

    public Set<ImGroupUser> getGroupUsersByGroupId(Long groupId) throws SQLException {
        return DbUtil.transaction((queryRunner, connection) -> {
            String sql = String.format("select %s from im_group_user gu where gu.groupId = ?", GU_COLUMNS);
            List<ImGroupUserExt> results =  queryRunner.query(connection, sql, new BeanListHandler<>(ImGroupUserExt.class), groupId);
            for (ImGroupUserExt groupUserExt : results) {
                groupUserExt.setUser(ImCacheFactory.getInstance().getUser(groupUserExt.getUserId()));
            }
            return results.stream().collect(Collectors.toSet());
        });
    }

    public void deleteGroupUsers(ImGroup imGroup, Set<ImUser> imUserSet) throws SQLException {
        DbUtil.transaction((queryRunner, connection) -> {
            String sql = String.format("delete from im_group_user where groupId = ? and userId = ?");
            for(ImUser imUser : imUserSet) {
                queryRunner.execute(sql, imGroup.getId(), imUser.getUserId());
            }
            return null;
        });
    }

    public void deleteGroupUsers(ImGroup imGroup) throws SQLException {
        DbUtil.transaction((queryRunner, connection) -> {
            String sql = String.format("delete from im_group_user where groupId = ?");
            queryRunner.execute(sql, imGroup.getId());
            return null;
        });
    }
}
